package com.wizo.csb.storages;

import com.wizo.csb.*;

import java.io.*;

import org.jets3t.service.Jets3tProperties;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.ServiceException;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.BaseVersionOrDeleteMarker;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.security.AWSCredentials;

public class AmazonS3 extends Storage{

	public static final String VERBOSE = "amazonS3.verbose";
	public static final String VERBOSE_DEFAULT = "true";
	
	public static final String AWS_ACCESS_KEY = "awsAccessKey";
	public static final String AWS_SECRET_KEY = "awsSecretKey";
	
	public static final String JETS3TPROPERTIES = "jets3tProperties";
	
	private S3Service _s3Service;
	private String _awsAccessKey;
	private String _awsSecretKey;
	private boolean _verbose;
	
	public AmazonS3(){
		
	}
	
	/**
	 * Initialize any state of this storage.
	 * Called once per storage instance; there is one storage instance per client thread
	 */
	public void init(){
		_verbose = Boolean.parseBoolean(getProperties().getProperty(VERBOSE, VERBOSE_DEFAULT));
		
		Jets3tProperties jets3tProps = new Jets3tProperties();
		try {
			jets3tProps = Jets3tProperties.getInstance(
					new FileInputStream(getProperties().getProperty(JETS3TPROPERTIES)),
					"jets3t.properties");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		_awsAccessKey = getProperties().getProperty(AWS_ACCESS_KEY);
		_awsSecretKey = getProperties().getProperty(AWS_SECRET_KEY);
		AWSCredentials credentials = new AWSCredentials(_awsAccessKey, _awsSecretKey);
		
		try{
			_s3Service = new RestS3Service(credentials, null, null, jets3tProps);
		}catch(S3ServiceException e){
			e.printStackTrace();
		}
	}

	@Override
	public InputStream download(String bucket, String name){
		S3Object s3Object;
		InputStream inputStream = null;
		try{
			s3Object = _s3Service.getObject(bucket, name);
		}catch(S3ServiceException e){
			e.printStackTrace();
			return inputStream;
		}
		
		try {
			inputStream = s3Object.getDataInputStream();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if(_verbose&&(inputStream!=null)){
			System.out.println("Download successfully! object:"+name);
		}
		
		return inputStream;
	}

	@Override
	public int upload(String bucket, String name, InputStream inputStream, 
			long contentLength, String contentType){
		S3Object fileObject = new S3Object(name);
		S3Bucket s3Bucket;

		try{
			s3Bucket = _s3Service.getBucket(bucket);
		}catch(S3ServiceException e){
			e.printStackTrace();
			return -1;
		}
		
		fileObject.setDataInputStream(inputStream);
		fileObject.setContentLength(contentLength);
		fileObject.setContentType("text/plain");
		
		try{
			fileObject = _s3Service.putObject(s3Bucket, fileObject);
		}catch(S3ServiceException e){
			e.printStackTrace();
			return -1;
		}
		
		if(_verbose){
			System.out.println("Upload successfully! object:"+name);
		}
	
		return 0;
	}
	
	@Override
	public int delete(String bucket, String name){
		S3Bucket s3Bucket;
		
		try{
			s3Bucket = _s3Service.getBucket(bucket);
		}catch(S3ServiceException e){
			e.printStackTrace();
			return -1;
		}
		
		try{
			_s3Service.deleteObject(s3Bucket, name);
		}catch(S3ServiceException e){
			e.printStackTrace();
			return -1;
		}
		
		if(_verbose){
			System.out.println("Delete successfully! object:"+name);
		}
		return 0;
	}
	
	@Override
	public int copy(String bucketS, String objectS, String bucketD, String objectD, 
			boolean replaceMetadata){
		try{
			_s3Service.copyObject(bucketS, objectS, bucketD, new S3Object(objectD), replaceMetadata);
		}catch(ServiceException e){
			e.printStackTrace();
			return -1;
		}
		
		if(_verbose){
			System.out.println("Copy successfully! object:"+objectS);
		}
		return 0;
	}
	
	@Override
	public int move(String bucketS, String objectS, String bucketD, String objectD, 
			boolean replaceMetadata){
		try{
			_s3Service.moveObject(bucketS, objectS, bucketD, new S3Object(objectD), replaceMetadata);
		}catch(ServiceException e){
			e.printStackTrace();
			return -1;
		}
		
		if(_verbose){
			System.out.println("Move successfully! object:"+objectS);
		}
		return 0;
	}
	
	public boolean getVersions(String bucket, String object){
		BaseVersionOrDeleteMarker[] versions = null;
		try{
			versions = _s3Service.getObjectVersions(bucket, object);
		}catch(S3ServiceException e){
			e.printStackTrace();
		}
		if(versions==null || versions.length==0){
			System.out.println("Object not exits");
			return false;
		}
		System.out.println("LastModifiedData: "+versions[0].getLastModified());
		return true;
	}
	
//	public static void main(String[] args){
//		AmazonS3 s3Storage = new AmazonS3();
//		s3Storage.init();
//		
//		String bucketName = "wizo.basicbucket";
//		long start, end;
//
//		System.out.println("Start");
//		
//		start = System.currentTimeMillis();
//		s3Storage.download(bucketName, "folder_1K/object_1", null);
//		end = System.currentTimeMillis();
//		System.out.println("Using time:"+(int)(end-start));
//		
//		start = System.currentTimeMillis();
//		s3Storage.download(bucketName, "folder_1K/object_1", null);
//		end = System.currentTimeMillis();
//		System.out.println("Using time:"+(int)(end-start));
//
//	}
}
